#!/usr/bin/python2

import sys

if (len(sys.argv) != 2):
    print "Usage: {0} /path/to/t/mjin2".format(sys.argv[0])
    sys.exit(0)

import pymjin2

class Mover(pymjin2.SequenceListener):
    def __init__(self, timer, node):
        self.i = 0
        self.node = node
        pymjin2.SequenceListener.__init__(self)
        self.sequence = pymjin2.Sequence(timer)
        self.sequence.setListener(self)
        # Setup points.
        f = 5
        rt = 1000
        p = pymjin2.SequencePoint()
        # (0, 0).
        p.append(0)
        p.append(0)
        self.sequence.addPoint(p, 0)
        # (f, f).
        p[0] = f
        p[1] = f
        self.sequence.addPoint(p, rt)
        # (f, -f).
        p[0] = f
        p[1] = -f
        self.sequence.addPoint(p, rt)
        # (0, 0).
        p[0] = 0
        p[1] = 0
        self.sequence.addPoint(p, rt)
        # (-f, f).
        p[0] = -f
        p[1] = f
        self.sequence.addPoint(p, rt)
        # (-f, -f).
        p[0] = -f
        p[1] = -f
        self.sequence.addPoint(p, rt)
        # (0, 0).
        p[0] = 0
        p[1] = 0
        self.sequence.addPoint(p, rt)
    def __del__(self):
        self.sequence.setListener(None)
        del self.sequence

    def onSequenceFinish(self):
        self.i += 1
        if (self.i > 2):
            self.i = 0
        if (self.i == 0):
            self.sequence.setInterpolation(pymjin2.SEQUENCE_INTERPOLATION_NONE)
        elif (self.i == 1):
            self.sequence.setInterpolation(pymjin2.SEQUENCE_INTERPOLATION_LINEAR)
        else:
            self.sequence.setInterpolation(pymjin2.SEQUENCE_INTERPOLATION_SPLINE)
        self.start()
    def onSequencePoint(self, p):
        self.node.setPosition(pymjin2.Vec3(p[0], self.node.position().y, p[1]))
    def start(self):
        self.sequence.start()

class Rotator(pymjin2.TimerListener):
    def __init__(self, timer, node):
        pymjin2.TimerListener.__init__(self)
        self.timer = timer
        self.node  = node
        self.timer.addListener(self, 0)
    def __del__(self):
        self.timer.removeListener(self)

    def onTimerTick(self, millisecondsElapsed):
        angle = millisecondsElapsed / 30.0
        r = pymjin2.rotationSum(
                self.node.rotation(),
                pymjin2.degreeToQuaternion(pymjin2.Vec3(0, angle, 0)))
        self.node.setRotation(r)

class Test(pymjin2.InputListener, pymjin2.WindowListener):
    def __init__(self, dataDir):
        self.app = pymjin2.Application("MJIN2", "log.html")
        self.wnd = pymjin2.Window("MJIN2", pymjin2.WindowConfig(800, 600, False));
        pymjin2.InputListener.__init__(self)
        self.wnd.addInputListener(self)
        pymjin2.WindowListener.__init__(self)
        self.wnd.addWindowListener(self)
        self.timer = pymjin2.Timer()
        self.wnd.setTimer(self.timer)
        # Scene.
        resolver = self.app.pathResolver()
        resolver.addSearchPath(dataDir)
        self.sceneNodeFactory = pymjin2.SceneNodeFactory()
        self.scene = pymjin2.Scene()
        cam = self.wnd.camera()
        cam.setPosition(pymjin2.Vec3(0, -60, 0))
        cam.setRotation(pymjin2.degreeToQuaternion(pymjin2.Vec3(90, 5, 0)))
        self.sceneNodeSelector = pymjin2.SceneNodeSelector()
        self.sceneNodeSelector.setCamera(cam)
        self.wnd.setScene(self.scene)
        self.truck = self.sceneNodeFactory.createMesh(
            "truck",
            resolver.findFile("dumptruck.osgt"))
        self.sceneNodeSelector.addNode(self.truck)
        self.box = self.sceneNodeFactory.createMesh(
            "box",
            resolver.findFile("box.osgt"),
            resolver.findFile("textures/wall.png"))
        self.sceneNodeSelector.addNode(self.box)
        self.scene.addChild(self.box)
        self.scene.addChild(self.truck)
        self.truck.setPosition(pymjin2.Vec3(15, 0, 0))
        self.truck.setRotation(pymjin2.rotationSum(
            pymjin2.degreeToQuaternion(pymjin2.Vec3(90, 45, 0)),
            pymjin2.degreeToQuaternion(pymjin2.Vec3(0, 45, 0))))
        # Absolute position.
        p = self.truck.positionAbs()
        print "a. truck abs pos: {0} {1} {2}".format(p.x, p.y, p.z)
        self.box.setPosition(pymjin2.Vec3(10, 0, 0))
        p = self.truck.positionAbs()
        print "b. truck abs pos: {0} {1} {2}".format(p.x, p.y, p.z)
        # Absolute rotation.
        r = self.truck.rotationAbs()
        print "a. truck abs rot: {0} {1} {2} {3}".format(r.x, r.y, r.z, r.w)
        self.box.setRotation(pymjin2.degreeToQuaternion(pymjin2.Vec3(0, 45, 0)))
        r = self.truck.rotationAbs()
        print "b. truck abs rot: {0} {1} {2} {3}".format(r.x, r.y, r.z, r.w)
        table = self.sceneNodeFactory.createMesh("table",
                                                 resolver.findFile("box.osgt"))
        table.setTexture(resolver.findFile("textures/wall.png"))
        self.sceneNodeSelector.addNode(table)
        self.scene.addChild(table)
        table.setScale(pymjin2.Vec3(8, 1, 6))
        table.setPosition(pymjin2.Vec3(0, 10, -5))
        table.setRotation(pymjin2.degreeToQuaternion(pymjin2.Vec3(25, 0, 0)))
        self.rotator = Rotator(self.timer, table)
        self.mover   = Mover(self.timer, table)
        self.mover.start()
        light = self.scene.light()
        light.setPosition(pymjin2.Vec4(4, -20, 5, 0))
        light.setAmbient(pymjin2.Vec4(0.2, 0.2, 0.2, 1))
        light.setDiffuse(pymjin2.Vec4(0.8, 0.8, 0.8, 1))
        line = self.sceneNodeFactory.createLine("line")
        verts = pymjin2.Vec3List()
        verts.append(pymjin2.Vec3(0,  -30, 0))
        verts.append(pymjin2.Vec3(10, -30, 0))
        verts.append(pymjin2.Vec3(5,  -30, 5))
        line.setColor(pymjin2.Vec4(1, 0, 0, 1))
        line.setVertices(verts)
        self.scene.addChild(line)
        self.wnd.setConfig(pymjin2.WindowConfig(640, 480, False))
    def __del__(self):
        del self.mover
        del self.rotator
        self.wnd.setTimer(None)
        del self.timer
        self.wnd.removeInputListener(self)
        self.wnd.removeWindowListener(self)
        self.wnd.setScene(None)
        del self.sceneNodeFactory
        del self.sceneNodeSelector
        del self.scene
        del self.wnd
        del self.app

    def onInput(self, e):
        if (e.press):
            if (e.input == pymjin2.INPUT_KEY_ESCAPE):
                print "Quit"
                self.wnd.stop()
            elif (e.input == pymjin2.INPUT_KEY_1):
                title = self.wnd.title()
                if (title == "MJIN2"):
                    title = "MJIN2 title change"
                else:
                    title = "MJIN2"
                print "Title change"
                self.wnd.setTitle(title)
            elif (e.input == pymjin2.INPUT_KEY_2):
                wc = self.wnd.config()
                if (wc.width == 640):
                    wc.width  = 800
                    wc.height = 600
                else:
                    wc.width  = 640
                    wc.height = 480
                print "resolution: {0}x{1}".format(wc.width, wc.height)
                self.wnd.setConfig(wc)
            elif (e.input == pymjin2.INPUT_KEY_3):
                wc = self.wnd.config()
                wc.fullScreen = not wc.fullScreen
                print "full screen:", wc.fullScreen
                self.wnd.setConfig(wc)
            elif (e.input == pymjin2.INPUT_KEY_4):
                wc = self.wnd.config()
                wc.vsync = not wc.vsync
                print "vsync:", wc.vsync
                self.wnd.setConfig(wc)
            elif (e.input == pymjin2.INPUT_KEY_5):
                wc = self.wnd.config()
                if (wc.antiAliasing == 0):
                    wc.antiAliasing = 2
                else:
                    wc.antiAliasing *= 2
                if (wc.antiAliasing > 16):
                    wc.antiAliasing = 0
                print "AA:", wc.antiAliasing
                self.wnd.setConfig(wc)
            elif (e.input == pymjin2.INPUT_KEY_6):
                wc = self.wnd.config()
                if (wc.fps == 0):
                    wc.fps = 60
                else:
                    wc.fps -= 10
                print "FPS:", wc.fps
                self.wnd.setConfig(wc)
            elif (e.input == pymjin2.INPUT_KEY_X):
                p = self.wnd.camera().position()
                print "cam pos: {0} {1} {2}".format(p.x, p.y, p.z)
                print "Key X {0} pressed".format(e.input)
                self.wnd.camera().setPosition(pymjin2.Vec3(0, -60, 0))
                self.wnd.camera().setRotation(
                    pymjin2.degreeToQuaternion(pymjin2.Vec3(90, 0, 0)))
                g = self.wnd.geometry()
                self.wnd.setMousePosition(int(g.z / 2), int(g.w / 2))
            elif (e.input == pymjin2.INPUT_KEY_B):
                r = pymjin2.rotationSum(self.box.rotation(),
                                        pymjin2.degreeToQuaternion(pymjin2.Vec3(0, 10, 0)))
                self.box.setRotation(r)
                print "mBox->setRotation({0}, {1}, {2}, {3})".format(r.x, r.y, r.z, r.w)
                p = self.truck.positionAbs()
                print "truck abs pos: {0} {1} {2}".format(p.x, p.y, p.z)
                r = self.truck.rotationAbs()
                print "truck abs rot: {0} {1} {2} {3}".format(r.x, r.y, r.z, r.w)
            elif (e.input == pymjin2.INPUT_KEY_T):
                r = pymjin2.rotationSum(self.truck.rotation(),
                                        pymjin2.degreeToQuaternion(pymjin2.Vec3(0, 10, 0)))
                self.truck.setRotation(r)
                print "mTruck->setRotation({0}, {1}, {2}, {3})".format(r.x, r.y, r.z, r.w)
            elif (e.input == pymjin2.INPUT_KEY_PAGE_DOWN):
                cfg = self.wnd.config()
                self.wnd.setConfig(cfg)
            elif (e.input == pymjin2.INPUT_MOUSE_BUTTON_LEFT   or
                  e.input == pymjin2.INPUT_MOUSE_BUTTON_MIDDLE or
                  e.input == pymjin2.INPUT_MOUSE_BUTTON_RIGHT):
                print "Mouse button. X: {0} Y: {1}".format(e.x, e.y)
                n = self.sceneNodeSelector.select(e.x, e.yi)
                if (n):
                    print "Selected node name: {0}".format(n.name())
                else:
                    print "No valid node returned"
            else:
                print "Unhandled input. Input: {0} UnmodifiedInput: {1} X: {2} Y: {3} Press: {4}".format(e.input, e.unmodifiedInput, e.x, e.y, e.press)
        else:
            print "Unhandled input. Input: {0} UnmodifiedInput: {1} X: {2} Y: {3} Press: {4}".format(e.input, e.unmodifiedInput, e.x, e.y, e.press)
    def onWindowClose(self):
        print "Quit"
    def onWindowRecreation(self):
        self.scene.recreateShadows()
    def run(self):
        self.wnd.run()

t = Test(sys.argv[1] + "/MJIN2")
t.run()
